home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / lastcom.zip / LASTCOM.PAS < prev    next >
Pascal/Delphi Source File  |  1993-01-04  |  8KB  |  214 lines

  1. {$c-}
  2. {$k-}
  3.  
  4. {this program is a "stay resident" program which allows the operator to
  5.  perform any of the last 10 commands which he had entered by entering an
  6.  AltF10 to get a list of them, followed by a function key F1-F10
  7.  to select which command to reenter.  Command lines which begin with
  8.  nonprintable keystrokes are not saved.  This program was written as an example
  9.  of a TurboPascal stay-resident program}
  10.  
  11. {declare our constants}
  12.  
  13. const
  14.     our_char = 113;                    {this is the scan code for AltF10}
  15.     scan_offset = 58;                  {scan code of F1 - 1}
  16.     first_row = 5;                     {window size and position}
  17.     first_col = 5;
  18.     numb_saved = 10;
  19.     windowwidth = 40;
  20.     windowlength = 12;                 {=numb_saved + 2}
  21.     CR = $D;
  22.     user_int = $68;                    {place to put out interrupt}
  23.     kybrd_int = $16;                   {BIOS keyboard interrupt}
  24.     prog_size = 16000;                 {approximate size of program --
  25.                                         this much space is reserved upon exit}
  26.  
  27. {here the global (static type) variables}
  28.  
  29. type
  30.     regtype = record
  31.                    ax,bx,cx,dx,bp,si,di,ds,es,flags:integer
  32.               end;
  33.     halfregtype = record
  34.                    al,ah,bl,bh,cl,ch,dl,dh:byte
  35.               end;
  36.  
  37. const                                  {pur 'regs' in the code segment}
  38.     regs : regtype = (ax:0;bx:0;cx:0;dx:0;bp:0;si:0;di:0;ds:0;es:0;flags:0);
  39.     feeding_char   :boolean = FALSE;
  40.     no_cr          :boolean = FALSE;
  41.     j              :integer = 1;
  42.     saveds         :integer = 0;
  43.  
  44. var
  45.     savreg         :regtype;           {define a variable for the structures}
  46.     halfregs       :halfregtype absolute regs; {and for the half registers}
  47.  
  48.     i              :integer;
  49.     last_lines     :array [0..numb_saved] of array[1..60] of integer;
  50.     cursorpos      :integer;
  51. {.pa}
  52. {include the window manipulation software}
  53. {$i window.inc}
  54. {.pa}
  55. {the following code prints out the previous n commands in
  56.  the window previously opened up}
  57.  
  58. procedure printchoices;
  59. var
  60.    i,j : integer;
  61.    outchar : byte;
  62.  
  63. begin
  64.    for i := 2 to numb_saved+1 do         {loop thru the saved commands}
  65.    begin
  66.       GoToXY(2,i);
  67.       Write('F');Write(((i-1) mod 10):1);Write(')'); {put up the command number}
  68.       j := 1;
  69.       while ((last_lines[i-1][j] and $FF) <> CR) and (j <> (windowwidth-5)) do
  70.       begin
  71.          Write(Chr(last_lines[i-1][j] and $FF));
  72.          j := j + 1
  73.       end
  74.    end
  75. end;
  76. {.pa}
  77. {this code processes interrupts to the get_char BIOS interrupt}
  78.  
  79. procedure process_intr;
  80. begin;
  81. {$i regsave.inc}                       {save the input registers}
  82.     if halfregs.ah = 0 then            {if this is character request...}
  83.     begin
  84.          if feeding_char then          {if we were in the middle of spooling chars...}
  85.          begin
  86.               regs.ax := last_lines[i][j]; {...fetch the next character...}
  87.               j := j + 1;
  88.               if (halfregs.al = CR) or (j > 60) then {...if this was the last character...}
  89.               begin
  90.                    feeding_char := false; {...turn spooling off}
  91.                    j := 1;
  92.                    if no_cr then
  93.                         regs.ax := $0;
  94.                    no_cr := false
  95.               end
  96.          end
  97.          else
  98.          begin                         {(we are not in the middle of spooling)}
  99.               Intr (user_int, regs);   {perform the BIOS call}
  100.               if halfregs.ah <> our_char then {if this wasn't "our" character...}
  101.               begin
  102.                    last_lines[0][j] := regs.ax; {...save the keystroke...}
  103.                    if j < 60 then
  104.                         j := j + 1;
  105.                    if halfregs.al = CR then     {...if that was a cr...}
  106.                    begin
  107.                         j := 1;                 {...pop down to next entry...}
  108.                         if Lo(last_lines[0][1]) <> 0 then {...if the first char was printable...}
  109.                              for i := numb_saved downto 1 do
  110.                                   last_lines[i] := last_lines[i-1];
  111.                         for i := 1 to 60 do     {...clear last entry}
  112.                              last_lines[0][i] := $07 shl 8 + CR
  113.                    end
  114.               end
  115.               else
  116.               begin
  117.                    savreg.ax := $0300;   {fetch the current cursor position}
  118.                    savreg.bx := $0;
  119.                    Intr($10,savreg);
  120.                    cursorpos := savreg.dx;
  121.  
  122.                    openwindow;         {open up the display window}
  123.                    printchoices;       {now print the last commands}
  124.                    regs.ax := $0;      {read a character from the keyboard}
  125.                    Intr(user_int,regs);
  126.  
  127.                    i := halfregs.ah - scan_offset;   {note that 0 maps to 1}
  128.                    if (i > 25) and (i < 37) then
  129.                    begin
  130.                         i := i - 25;
  131.                         no_cr := true
  132.                    end;
  133.                    if (i > 0) and (i <= 10) then
  134.                    begin               {legal input}
  135.                         regs.ax := last_lines[i][1]; {give him the first char}
  136.  
  137.                         if halfregs.al <> CR then
  138.                         begin
  139.                              feeding_char := true;
  140.                              j := 2
  141.                         end;
  142.  
  143.                    end;
  144.                    closewindow;        {put what was there back}
  145.  
  146.                    savreg.ax := $0200; {reposition cursor}
  147.                    savreg.bx := $0;
  148.                    savreg.dx := cursorpos;
  149.                    Intr($10,savreg)
  150.               end
  151.          end
  152.     end
  153.     else                               {he's not trying t read a character}
  154.          if feeding_char then          {if he's spooling characters...}
  155.               regs.flags := regs.flags and $FFBF {...clear the zero bit}
  156.          else
  157.               Intr(user_int,regs);
  158.  
  159. {$i regrstor.inc}                      {restore the registers from 'reg'}
  160.     inline($CA/$02/$00)                {RETF 02}
  161. end;
  162. {.pa}
  163. {this section of code installs the interrupt routine and makes it permanently
  164.  resident interrupt borrower}
  165.  
  166. {the following dos calls are used:
  167.  sys 25- install interrupt address
  168.    input al = int number, ds:dx = address to install
  169.  
  170.  sys 35- get interrupt address
  171.    input al = int number
  172.    output es:bx = address in interrupt
  173.  
  174.  int 27- terminate and stay resident
  175.    input dx = size of resident program
  176. }
  177. begin                                  {**main**}
  178.     {initialize the variables which the interrupt service routine will use}
  179.  
  180.     for i := 0 to numb_saved do
  181.          for j := 1 to 60 do
  182.               last_lines[i][j] := $07 shl 8 + CR;
  183.     j := 1;
  184.     saveds := Dseg;                    {save the data segment locally}
  185.  
  186.     {now install the interrupt routine}
  187.  
  188.     savreg.ax := $35 shl 8 + user_int; {check to make sure int not already used}
  189.     Intr($21,savreg);
  190.     if savreg.es <> $00 then
  191.          WriteLn ('Interrupt in use -- cant install LASTCOMMAND')
  192.     else
  193.     begin
  194.          WriteLn ('Installing LASTCOMMAND -- press AltF10 to select last command');
  195.  
  196.          savreg.ax := $35 shl 8 + kybrd_int;{get the address that was there}
  197.          Intr($21,savreg);
  198.  
  199.          savreg.ax := $25 shl 8 + user_int; {put the address in the user interrupt}
  200.          savreg.ds := savreg.es;
  201.          savreg.dx := savreg.bx;
  202.          Intr($21,savreg);
  203.  
  204.          savreg.ax := $25 shl 8 + kybrd_int;{install interrupt system call}
  205.          savreg.ds := cseg;
  206.          savreg.dx := Ofs(process_intr);    {put our routine address}
  207.          Intr ($21,savreg);
  208.  
  209.          {now terminate and stay resident}
  210.  
  211.          savreg.dx := prog_size;
  212.          Intr ($27,savreg)
  213.     end
  214. end.